(function(angular) {
	"use strict";
	angular.module("fs.waf").factory("settleInitRepayService", settleInitRepayService);
	settleInitRepayService.$inject = [ "$injector", "clsConstants", "$filter", "formatService", "arithService", "payDetailService", "setlDetailService", "txnService" ];
	function settleInitRepayService($injector, clsConstants, $filter, formatService, arithService, payDetailService, setlDetailService, txnService) {

		function initSettlement(settlement) {
			// payment detail contains discrepancy entry
			settlement.hasDiscrepancy = false;
			// trace the discrepancy paydetail entry, its value is a
			// PayDetailSeqAndIndex object
			settlement.disEntry = getDisEntry(settlement.payDetails);
			// trace the itemSubtype(REMITTANCE) paydetail entry only for remittance payment
			settlement.rPaydetailEntry = getRPaydetailEntry(settlement);
			// if process priority
			settlement.hasPriority = false;
			if (settlement.payment.repayType == "M" && settlement.payment.payPriority != "NONE" && (settlement.payment.incIntFlag == "Y" || settlement.payment.incFeeFlag == "Y")) {
				settlement.hasPriority = true;
			}
			// trace the priority list, the index is the itemOrder in settlement
			// details
			settlement.priorityList = new Array();
			setDisPayCode(settlement);
		}
		
		function setDisPayCode(settlement){
			settlement.disPayCode = [];
			angular.forEach(settlement.txnSetlInsts, function(txnSetlInst){
				if(txnSetlInst.itemType == "D"){
					settlement.disPayCode[txnSetlInst.crDr] = txnSetlInst;
				}
			});
		}

		function getCompanyCodeByAlloc(settlement, allocCode) {
			var custCode = "", encode = $filter("encode");
			if (allocCode == "CUSTOMER")
				custCode = encode(settlement.loan.loanInfo.custCode);
			else if (allocCode == "OBLIGOR")
				custCode = encode(settlement.loan.loanInfo.obligorCode);
			else
				custCode = encode(settlement.loan.loanInfo.custCode);

			return custCode;
		}

		function getProdCodeAndType(settlement) {
			var prodCode = settlement.loan.loanInfo.prodCode;
			var prodType = settlement.loan.loanInfo.prodType;
			return {
				prodCode : prodCode,
				prodType : prodType
			};
		}

		function getGeneralConfig(layoutConfig) {
			return angular.copy(layoutConfig.formConfigs.repayment);
		}
		
		function getGeneralModel(settlement) {
			return settlement.payment;
		}
		
		function processDynaparmConfig(loyout){
			angular.forEach(loyout.formConfigs.repayment.gridConfigs, function(gridConfig){
				if(gridConfig.model.indexOf("dynamicParams.") != -1){
					gridConfig.model = "payment." + gridConfig.model;
				}
			});
		}
		
		function getBackMessage() {
			return "title.infobar.repay.update";
		}

		function getDeductIntAndFeeFlag(settlement) {
			return {
				deductIntFlag : settlement.payment.incFeeFlag,
				deductFeeFlag : settlement.payment.incIntFlag
			};
		}
		
		function getHoldFeeFlag(settlement){
			return settlement.payment.holdFeeFlag;
		}

		function getRPaydetailEntry(settlement) {
			var rPaydetailEntry = {}, i = 0, repayType = settlement.payment.repayType;
			for (i = 0; i < settlement.payDetails.length; i++) {
				if ((settlement.payDetails[i].itemSubtype == clsConstants.PayDetailItemSubType.ROLLOVER || 
						settlement.payDetails[i].itemSubtype == clsConstants.PayDetailItemSubType.REMITTANCE) && (repayType == "M" || repayType == "G")) {
					rPaydetailEntry = settlement.payDetails[i];
					break;
				}
			}
			return rPaydetailEntry;
		}

		function getDisEntry(payDetails) {
			var disEntry = undefined;
			for (var i = 0; i < payDetails.length; i++) {
				if (payDetails[i].itemType == "D" || payDetails[i].itemSubtype == clsConstants.PayDetailItemSubType.DISCREPANCY) {
					disEntry = payDetails[i];
					break;
				}
			}
			return disEntry;
		}

		function dynamicConfigItemCarryFlag(settlement, item) {
			var repayType = settlement.payment.repayType;
			var finalPayment = settlement.payment.finalRepayFlag;
			if ((item.itemType != "P") && ((finalPayment) || (repayType == "R" && item.uItemTransfer == "Y"))) {
				if (item.itemTransferFlag == "Y") {
					item.itemCarryFlag_Readonly = true;
				}
			}
		}
		/**
		 * item is settlement detail DynamicConfigSetldetail method will call
		 * it.
		 */
		function dynamicConfigItemHoldFlag(settlement, item) {
			var repayType = settlement.payment.repayType;
			var finalPayment = settlement.payment.finalRepayFlag;
			if (item.itemType == "I" && item.childFlag == "N") {
				if (repayType != "R") {
					if (finalPayment == false) {
						if (item.itemSubtype != clsConstants.SetlDetailItemSubType.INTEREST_REFUND) {
							item.itemHoldFlag_Show = true;
						}
					} else if (finalPayment) {
						item.itemHoldFlag_Show = true;
					}
				}
			}

			if (repayType == "R" && item.itemType != "P" && item.uItemCarryovere == "Y") {// 2006.3.15
				if (item.itemCarryoverFlag == "Y") {
					item.itemHoldFlag_Readonly = true;
				}
			}
			if ((item.itemType != "P") && ((finalPayment) || (repayType == "R" && item.uItemTransfer == "Y"))) {
				if (item.itemTransferFlag == "Y") {
					item.itemHoldFlag_Readonly = true;
				}
			}
		}

		function dynamicConfigItemWaiveFlag(settlement, item) {
			var repayType = settlement.payment.repayType;
			var finalPayment = settlement.payment.finalRepayFlag;
			if (item.itemType == "I" && item.childFlag == "N") {
				if (repayType != "R") {
					if (finalPayment == false) {
						if (item.itemSubtype != clsConstants.SetlDetailItemSubType.INTEREST_REFUND) {
							item.itemWaiveFlag_Show = true;
						}
					} else if (finalPayment) {
						item.itemWaivFlag_Show = true;
					}
				}
			}
			if (repayType == "R" && setlDetail.itemType != "P" && item.uItemCarryovere == "Y") {
				if (item.itemCarryoverFlag == "Y") {
					item.itemWaiveFlag_Readonly = true;
				}
			}
			if ((item.itemType != "P") && ((finalPayment) || (repayType == "R" && item.uItemTransfer == "Y"))) {
				if (item.itemTransferFlag == "Y") {
					item.itemWaiveFlag_Readonly = true;
				}
			}
		}

		function dynamicConfigItemTransferFlag(settlement, item) {
			var repayType = settlement.payment.repayType, finalPayment = settlement.payment.finalRepayFlag;
			item.itemTransferFlag_Show = false;
			if (item.itemType == "I" && item.childFlag == "N") {
				if (repayType != "R") {
					if (finalPayment == false) {
						if (item.itemSubtype != clsConstants.SetlDetailItemSubType.INTEREST_REFUND) {
							item.itemTransferFlag_Show = true;
						}
					} else if (finalPayment) {
						item.itemTransferFlag_Show = true;
					}
					if (item.uItemTransfer == "Y") {
						item.itemTransferFlag_Show = true;
					}
				}
			}
		}

		function initSettlementData(setlDetail, settlement) {
			// added on 2006.9.8
			adjustPayCcyByAllocCode(settlement, setlDetail, false, false);
			// make sure all the index of vo are valid
			var isRolloverFlag = isRolloverPayment(settlement);
			// handled the refund interest on product settings 2006.8.1 by Shu
			var itemOrderVal = setlDetail.itemOrder;
			if (setlDetail.itemSubtype == clsConstants.SetlDetailItemSubType.INTEREST_NO_REFUND) {
				setlDetail.setlDetail_Readonly = false;
			}
			// 20060812 build the pay priority list
			if (isControllPriority(settlement, setlDetail)) {
				settlement.priorityList[itemOrderVal] = setlDetail;
				adjustPayAmtForPayPriority(settlement, setlDetail);
				payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
				setlDetailService.disableSplit(setlDetail, false);
			}
			// 2006.9.7 principal is not split when rollover repayment
			if (isRolloverFlag) {
				var itemTypeObj = setlDetail.itemType;
				if (itemTypeObj != null && itemTypeObj == "P") {
					setlDetailService.disableSplit(setlDetail, false);
				}
			}
		}
		/***********************************************************************
		 * Check if this settlement parent type is rollover repayment. return
		 * true if rollover repayment, otherwise return false.
		 **********************************************************************/
		function isRolloverPayment(settlement) {
			var payTypeVal = settlement.payment.repayType;
			if (payTypeVal == "R")
				return true;
			else
				return false;
		}
		/***********************************************************************
		 * Check if the settlement detail item need to pay priority. if need,
		 * return true; otherwise false. itemNo: the index of settlement details
		 **********************************************************************/
		function isControllPriority(settlement, setlDetail) {
			var isControlPriority = false;
			if (setlDetail.itemType && settlement.hasPriority) {
				var includeFee = settlement.payment.incFeeFlag;
				var includeInt = settlement.payment.incIntFlag;
				var payMethod = settlement.rPaydetailEntry.payItemSeq;
				if ((setlDetail.crDrFlag == "D") && (setlDetail.paydetailSeq && setlDetail.paydetailSeq == payMethod) && (settlement.settlementInfo.principalAlloc == setlDetail.allocCode)
						&& (setlDetail.itemSubtype != clsConstants.SetlDetailItemSubType.OTHER_BANK_FEE)) {
					if ((setlDetail.itemType == "I" && includeInt == "Y") || (setlDetail.itemType == "F" && includeFee == "Y") || (setlDetail.itemType == "P"))
						isControlPriority = true;
				}
			}
			return isControlPriority;
		}
		/***********************************************************************
		 * Adjust the payAmt when this settlement detail entry is unchecked on
		 * hold/waive checkbox. if the payAmt is greater than the actual payable
		 * amount then reset the itemAmtSettled by actual payAmt. itemNo: array
		 * index of settlement detail items
		 **********************************************************************/
		function adjustPayAmtForPayPriority(settlement, setlDetail) {
			var bccy = settlement.site.baseCcy;
			var payccy = setlDetail.payCcy;
			var variableAmt = formatService.parseNumber(setlDetail.payAmt);
			var order = setlDetail.itemOrder;
			var crDrValue = setlDetail.crDrFlag;
			if (settlement.hasPriority && crDrValue == "D" && settlement.priorityList[order] != null) {
				var payCcyVal = settlement.payment.payCcy;
				var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
				var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
				var fxRate1Val = setlDetail.fxRate - 0;
				if (fxRate1Val == 0) {
					fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
				}
				var variableAmtInRemitCcy = getFinalAmt(variableAmt, payccy, payCcyVal, fxRate1Val, payCcyFxRate);
				// alert("adjustPayAmtForPayPriority variableAmtInRemitCcy="+variableAmtInRemitCcy+",payAmtTotalVal"+payAmtTotalVal);
				if (variableAmtInRemitCcy > payAmtTotalVal) {
					variableAmt = getFinalAmt(payAmtTotalVal, payCcyVal, payccy, payCcyFxRate, fxRate1Val);
					setlDetail.payAmt = variableAmt;
					var itemAmtValTmp = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
					setlDetail.itemAmtSettled = itemAmtValTmp;
					setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtValTmp);
				}
			}
		}

		// calculate itemAmtSetled by pay amount for settlement detail.
		// return a formated amount.
		// itemNo: array index of settlementDetails
		/**
		 * calculate itemAmtSetled by pay amount for settlement detail.
		 * return a formated amount.
		 * setlDetail: array index of settlementDetails
		 */
		function calculateItemAmtSetledByPayAmt(settlement, setlDetail) {
			var itemccy = setlDetail.itemCcy;
			var payAmtVal = formatService.parseNumber(setlDetail.payAmt);
			var payccy = setlDetail.payCcy;
			var fxRate = formatService.parseNumber(setlDetail.fxRate);
			var fxRate2 = formatService.parseNumber(setlDetail.fxRate2);
			var fxr1 = null;
			var fxr2 = null;
			if (fxRate) {
				fxr1 = arithService.calc(fxRate, 0, "-");
			}
			if (fxRate2) {
				fxr2 = arithService.calc(fxRate2, 0, "-");
			}
			var baseCcy = settlement.site.baseCcy;
			var fxMulflag = settlement.site.isFxMultiply;
			var itemAmt = 0;
			var tmpamt = 0;

			if (arithService.eq(fxr1, 0) && arithService.eq(fxr2, 0))
				return formatService.parseMoney(formatService.formatMoney(payAmtVal + "", itemccy));

			if (itemccy == payccy) {// No rate
				return formatService.parseMoney(formatService.formatMoney(payAmtVal + "", itemccy));
			} else {
				if (itemccy != baseCcy && payccy != baseCcy) {// fxRate1 and
					// fxRate2
					tmpamt = (fxMulflag == "Y") ? arithService.calc(arithService.calc(payAmtVal, fxr1, "*"), fxr2, "/") : arithService.calc(arithService.calc(payAmtVal, fxr1, "/"), fxr2, "*");
				}
				if (itemccy != baseCcy && payccy == baseCcy)// fxRate2
					tmpamt = (fxMulflag == "Y") ? arithService.calc(payAmtVal, fxr2, "/") : arithService.calc(payAmtVal, fxr2, "*");
				if (payccy != baseCcy && itemccy == baseCcy)// fxRate1
					tmpamt = (fxMulflag == "Y") ? arithService.calc(payAmtVal, fxr1, "*") : arithService.calc(payAmtVal, fxr1, "/");
			}

			itemAmt = formatService.parseMoney(formatService.formatMoney(tmpamt + "", itemccy));
			return itemAmt;
		}

		/***********************************************************************
		 * get the max amount to pay for the assigned settlement detail. The
		 * amount is pure digital. itemNo: the index of settlement details
		 **********************************************************************/
		function getMaxRemitAmt(settlement, setlDetail) {
			var payCcyVal = settlement.payment.payCcy;
			var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
			var payAmtTotalVal = formatService.parseNumber(settlement.payment.repayAmt);
			var thisOrderVal = setlDetail.itemOrder;
			var bccy = settlement.site.baseCcy;
			if (settlement.hasPriority) {
				for ( var order in settlement.priorityList) {
					if (settlement.priorityList[order] == null)
						continue;
					if (thisOrderVal * 1 > order * 1) {
						var setlDetail1 = settlement.priorityList[order];
						var itemTypeObj = setlDetail1.itemType;
						var payItemSeqObj = setlDetail1.paydetailSeq;
						if (itemTypeObj == null)
							continue;
						if (payItemSeqObj.paydetailSeq_Readonly == true)
							continue;
						var holdObj = setlDetail1.itemHoldFlag;
						if (holdObj == "Y")
							continue;
						var waiveObj = setlDetail1.itemWaiveFlag;
						if (waiveObj == "Y")
							continue;

						var payccy = setlDetail1.payCcy;
						var payAmtVal = formatService.parseNumber(setlDetail1.payAmt);
						var fxRate1Val = setlDetail1.fxRate - 0;
						if (fxRate1Val == 0) {
							fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
						}
						var payAmtValInRemitCcy = getFinalAmt(payAmtVal, payccy, payCcyVal, fxRate1Val, payCcyFxRate);
						payAmtTotalVal = arithService.calc(payAmtTotalVal, payAmtValInRemitCcy, "-");
					}
				}
			}
			var itemTypeObj = setlDetail.itemType;
			if (arithService.gt(payAmtTotalVal, 0) && itemTypeObj == "F") {
				var itemAmt = formatService.parseNumber(setlDetail.itemAmt);
				var itemCcy = setlDetail.itemCcy;
				var fxRate2Val = formatService.parseNumber(setlDetail.fxRate2) - 0;
				if (fxRate2Val == 0) {
					fxRate2Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", bccy, itemCcy);
				}
				var itemAmtInPaymentPayCcy = getFinalAmt(itemAmt, itemCcy, payCcyVal, fxRate2Val, payCcyFxRate);
				if (payAmtTotalVal <= itemAmtInPaymentPayCcy)
					payAmtTotalVal = itemAmtInPaymentPayCcy;
			}
			return payAmtTotalVal;
		}

		/***********************************************************************
		 * Get the final pure, unformated amount in toCcy by fromAmt in fromCcy
		 * only for debit settlement details(buyer rate)
		 **********************************************************************/
		function getFinalAmt(fromAmt, fromCcy, toCcy, fromRate, toRate) {
			if (fromCcy == toCcy)
				return formatService.parseNumber(formatService.formatMoney(fromAmt, toCcy));
			fromRate = formatService.round(fromRate, 9);
			toRate = formatService.round(toRate, 9);
			var bccy = settlement.site.baseCcy;
			var fxMultiply = settlement.site.isFxMultiply;
			var tmpamt = 0;
			if (fromCcy != bccy && toCcy != bccy) {
				tmpamt = (fxMultiply == "Y") ? arithService.calc(arithService.calc(fromAmt, fromRate, "*"), toRate, "/") : arithService.calc(arithService.calc(fromAmt, fromRate, "/"), toRate, "*");
			} else if (fromCcy != bccy && toCcy == bccy) {
				tmpamt = (fxMultiply == "Y") ? arithService.calc(fromAmt, fromRate, "*") : arithService.calc(fromAmt, fromRate, "/");
			} else if (fromCcy == bccy && toCcy != bccy) {
				tmpamt = (fxMultiply == "Y") ? arithService.calc(fromAmt, toRate, "/") : arithService.calc(fromAmt, toRate, "*");
			}

			return formatService.parseNumber(formatService.formatMoney(tmpamt, toCcy));
		}

		/***********************************************************************
		 * Check if this settlement parent type is remittance repayment. return
		 * true if remittance repayment, otherwise return false.
		 **********************************************************************/
		function isRemittancePayment(settlement) {
			var payTypeVal = settlement.payment.repayType;
			if ((payTypeVal == "M" || payTypeVal == "G"))
				return true;
			else
				return false;
		}
		/***********************************************************************
		 * Check if the amount is greater than remittance amount only when pay
		 * priority. It must be called in final. If greater or less, set the
		 * remittance amount to this amount and the discrepancy amount is moved
		 * to the discrepancy item.
		 **********************************************************************/
		function formatRemitPayDetailItems(settlement) {
			var remitAmtVal = settlement.payment.repayAmt;
			settlement.rPaydetailEntry = getRPaydetailEntry(settlement);
			var payMethodVal = settlement.rPaydetailEntry.payItemSeq;
			var payAmtObj = settlement.rPaydetailEntry.payAmt;
			var payCcyVal = settlement.rPaydetailEntry.payCcy;
			var payCrDrVal = settlement.rPaydetailEntry.crDrFlag;
			var rAmt = payAmtObj;
			// deduct other settlement details" amount
			var pureAmt = 0;
			var continueFlag = true;
			angular.forEach(settlement.setlDetails, function(data, index, array) {
				if (data.itemSubtype == clsConstants.SetlDetailItemSubType.INTEREST_NO_REFUND)
					continueFlag = false;
				if (!data.itemType)
					continueFlag = false;
				if (continueFlag) {
					// var payIdObjTmp = data.paydetailSeq;
					// var payIdVal = payIdObjTmp.value;
					// if(payIdObjTmp.disabled == true)
					// payIdVal = null;
					if ((data.paydetailSeq && payMethodVal == data.paydetailSeq)) {
						var payAmtInSDVal = data.payAmt;
						var crDrInSDVal = data.crDrFlag;
						if (payCrDrVal == crDrInSDVal)
							pureAmt = arithService.calc(pureAmt, payAmtInSDVal, "+");
						else
							pureAmt = arithService.calc(pureAmt, payAmtInSDVal, "-");
					}
				}
			});
			// transfer the plus amount
			// alert("formatRemitPayDetailItems ()
			// pureAmt="+pureAmt+",remitAmtVal="+remitAmtVal);
			if (arithService.gt(pureAmt, remitAmtVal)) {
				var plusAmtTmp = arithService.calc(pureAmt, remitAmtVal, "-");
				rAmt = remitAmtVal;
				payDetail.payAmt = rAmt;
				if (settlement.disEntry) {
					if (settlement.disEntry.crDrFlag == "C") {
						disAmt = plusAmtTmp;
						settlement.disEntry.crDrFlag = "D";
						payDetailService.dynamicChangeThePayCodeList(settlement.disEntry, settlement);
					} else {
						disAmt = plusAmtTmp;
					}
					settlement.disEntry.payAmt = disAmt;
				} else {
					// create a new debit discrepancy
					createDiscrepancyPaydetail(settlement, payCcyVal, "D", plusAmtTmp);
				}
			} else if (arithService.lt(pureAmt, remitAmtVal)) {
				rAmt = remitAmtVal;
				var plusAmtTmp = arithService.calc(remitAmtVal, pureAmt, "-");
				settlement.rPaydetailEntry.payAmt = rAmt;
				if (settlement.disEntry != null) {
					var disAmt = settlement.disEntry.payAmt;
					if (settlement.disEntry.crDrFlag == "C") {
						disAmt = plusAmtTmp;
					} else {
						disAmt = plusAmtTmp;
						settlement.disEntry.crDrFlag = "C";
						payDetailService.dynamicChangeThePayCodeList(settlement.disEntry, settlement);
					}
					settlement.disEntry.payAmt = disAmt;
				} else {
					// create a new credit discrepancy
					createDiscrepancyPaydetail(settlement, payCcyVal, "C", plusAmtTmp);
				}
			} else {
				rAmt = remitAmtVal;
				settlement.rPaydetailEntry.payAmt = rAmt;
				if (settlement.disEntry != null) {
					settlement.disEntry.payAmt = settlement.disEntry.payAmt;
				}
			}
		}

		/***********************************************************************
		 * create a new discrepancy payment detail entry. payCcy: the pay
		 * currency of the payment details crDr: the credit or debit: C or D
		 * amtInPayCcy: the pay amount in pay currency
		 **********************************************************************/
		function createDiscrepancyPaydetail(settlement, payCcy, crDr, amtInPayCcy) {
			var allocCode = settlement.settlementInfo.principalAlloc;
			if (settlement.disPayCode[crDr] != null) {
				allocCode = settlement.disPayCode[crDr].allocCode;
			}
			var setlDetail = {
				crDrFlag : crDr,
				payCcy : payCcy,
				allocCode : allocCode
			};

			var payDetail = payDetailService.addPayDetailRow(settlement, setlDetail, false, true);
			setlDetail.paydetailSeq = payDetail.payItemSeq;
			setlDetailService.initializeSetlPayIdData(setlDetail);
			payDetailService.changePaydetailBySetldetail(settlement, setlDetail);

			resetDispPaydetailAcctByInstruction(settlement, crDr, settlement.disEntry);
			// set amount
			settlement.disEntry.payAmt = amtInPayCcy;
		}
		/***********************************************************************
		 * //Only when remittance repayment, the rPaydetailEntryIndex paydetail
		 * item(itemSubtype=R) crdr //always is debit. In processing of operation
		 * on settlement init screen, its amount //can be less than the deleted
		 * settlement detail item amount, //in this case it"s crDr can be
		 * changed to credit from original debit. //So we must reset it"s crdr
		 * as debit. //This method is only for remittance.
		 **********************************************************************/
		function resetRPaydetailEntryCrdr(settlement) {
			if (isRemittancePayment(settlement) && settlement.rPaydetailEntry) {
				if (settlement.rPaydetailEntry.crDrFlag == "C") {
					settlement.rPaydetailEntry.crDrFlag = "D";
				}
			}
		}
		function doChangePayCcy(settlement) {
			if (isRemittancePayment(settlement)) {
				resetRPaydetailEntryCrdr(settlement);
				formatRemitPayDetailItems(settlement);
			}
		}
		function changeAmountBox(settlement, setlDetail) {
			resetSetlDetailPayAmt(settlement, setlDetail, "N");
			if (isRemittancePayment(settlement)) {
				// pay priority
				var oldPayAmtVal = formatService.parseNumber(setlDetail.payAmt);
				var order = setlDetail.itemOrder;
				var payCcyVal = setlDetail.payCcy;
				if (settlement.hasPriority && setlDetail.crDrFlag == "D" && settlement.priorityList[order] != null && setlDetail.paydetailSeq_Readonly == false) {
					var baseCcy = settlement.site.baseCcy;
					var paymentPayCcyVal = settlement.payment.payCcy;
					var paymentPayCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", baseCcy, paymentPayCcyVal);
					var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
					var fxRate1Val = formatService.parseNumber(setlDetail.fxRate) - 0;
					if (fxRate1Val == 0) {
						fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", baseCcy, payCcyVal);
					}
					var newPayAmtVal = formatService.parseNumber(retObj.returnAmt + "");
					var newPayAmtInRemitCcy = getFinalAmt(newPayAmtVal, payCcyVal, paymentPayCcyVal, fxRate1Val, paymentPayCcyFxRate);
					// alert("oldPayAmtVal="+oldPayAmtVal+",maxRemitAmt="+payAmtTotalVal+",newPayAmtInRemitCcy="+newPayAmtInRemitCcy);
					if (newPayAmtInRemitCcy > payAmtTotalVal) {
						newPayAmtVal = getFinalAmt(payAmtTotalVal, paymentPayCcyVal, payCcyVal, paymentPayCcyFxRate, fxRate1Val);
						setlDetail.payAmt = newPayAmtVal;
						itemAmtSetledVal = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
						setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtSetledVal);
						payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
					}
					// collection balance from other source
					var dispAmt = arithService.calc(oldPayAmtVal, newPayAmtVal, "-");
					// alert("dispAmt="+dispAmt);
					var paramObj = new Object();
					paramObj.ccy = payCcyVal;
					paramObj.fxRate = fxRate1Val;
					paramObj.order = order;
					paramObj.amtType = "pay";
					paramObj.amt = dispAmt;
					adjustPayPriorityAmt(settlement, paramObj);
					formatRemitPayDetailItems(settlement);
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		function fxCrossRateChanged(settlement, setlDetail, oldPayAmt) {
			if (isRemittancePayment(settlement)) {
				if (settlement.hasPriority && setlDetail.crDrFlag == "D" && settlement.priorityList[order] != null && setlDetail.paydetailSeq_Readonly == false) {
					var bccy = settlement.site.baseCcy;
					var payccy = setlDetail.payCcy;
					var itemccy = setlDetail.itemCcy;
					var order = setlDetail.itemOrder;
					var payCcyVal = settlement.payment.payCcy;
					var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
					var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
					if (formatService.parseNumber(setlDetail.fxRate) == 0) {
						setlDetail.fxRate = getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
					}
					var variableAmt = formatService.parseNumber(amt);
					var crossRateConfig = (itemccy == payCcyVal) ? {
						crossRateFlag : fxCrossRateService.FxCrossRate_Util.getFxCrossRateFlagVal(setlDetail),
						crossRateFromItemCcyToPayCcy : fxCrossRateService.FxCrossRate_Util.getFxCrossRateVal(setlDetail),
						amt : variableAmt,
						amtType : "payAmt"
					} : {};
					var variableAmtInRemitCcy = getFinalAmt(variableAmt, payccy, payCcyVal, setlDetail.fxRate, payCcyFxRate, crossRateConfig);
					// alert("maxRemitAmt="+payAmtTotalVal+",variableAmtInRemitCcy"+variableAmtInRemitCcy);
					if (variableAmtInRemitCcy > payAmtTotalVal) {
						crossRateConfig = (itemccy == payCcyVal) ? {
							crossRateFlag : fxCrossRateService.FxCrossRate_Util.getFxCrossRateFlagVal(setlDetail),
							crossRateFromItemCcyToPayCcy : fxCrossRateService.FxCrossRate_Util.getFxCrossRateVal(setlDetail),
							amt : payAmtTotalVal,
							amtType : "itemAmt"
						} : {};
						variableAmt = getFinalAmt(payAmtTotalVal, payCcyVal, payccy, payCcyFxRate, setlDetail.fxRate, crossRateConfig);
						setlDetail.payAmt = variableAmt;
						var itemAmtValTmp = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
						setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtValTmp);
						payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
					}
					// collection balance from other source
					var dispAmt = arithService.calc(oldPayAmt, variableAmt, "-");
					var paramObj = new Object();
					paramObj.ccy = payccy;
					paramObj.fxRate = setlDetail.fxRate;
					paramObj.order = order;
					paramObj.amtType = "pay";
					paramObj.amt = dispAmt;
					adjustPayPriorityAmt(settlement, paramObj);
					formatRemitPayDetailItems(settlement);
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		/***********************************************************************
		 * adjust the pay priority list from the start order using adjustAmt
		 * obj: the Object, fields: ccy,order,amtType,amt
		 **********************************************************************/
		function adjustPayPriorityAmt(settlement, obj) {
			var startOrder = obj.order;
			var adjustAmt = obj.amt;
			// alert("adjustAmt="+adjustAmt+",startOrder="+startOrder+",amtType="+obj.amtType);
			if (settlement.priorityList[startOrder] != null) {
				if (adjustAmt > 0) {
					addPriorityAmt(settlement, obj);
				} else if (adjustAmt < 0) {
					obj.amt = -adjustAmt;
					deductPriorityAmt(settlement, obj);
				} else
					return;
			}
		}

		/***********************************************************************
		 * deduct the amount from the lower priority item than this start order
		 * obj: the Object, fields: ccy,order,amtType,amt
		 **********************************************************************/
		function deductPriorityAmt(settlement, obj) {
			var adjustAmt = obj.amt;
			var adjustCcy = obj.ccy;
			var startOrder = obj.order;
			var adjustCcyFxRate = formatService.parseNumber(obj.fxRate + "");
			var baseCcy = settlement.site.baseCcy;
			var remitAmtVal = formatService.parseNumber(settlement.payment.repayAmt);
			// current entry
			var setlDetail = settlement.priorityList[startOrder];
			var payItemSeqObj = setlDetail.paydetailSeq;
			var setledAmtObj = setlDetail.itemAmtSettled;
			var setledAmt = formatService.parseNumber(setledAmtObj);
			var itemAmt = formatService.parseNumber(setlDetail.itemAmt);
			var itemCcy = setlDetail.itemCcy;
			var itemType = setlDetail.itemType;
			var itemFxRate2 = setlDetail.fxRate2 - 0;
			if (itemFxRate2 == 0)
				itemFxRate2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, itemCcy);

			var adjustAmtInItemCcy = getFinalAmt(adjustAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2);
			setledAmt = 0;
			// discrepancy
			var payMethodVal = settlement.rPaydetailEntry.payItemSeq;
			var payCcyVal = settlement.rPaydetailEntry.payCcy;
			var payAmtObj = settlement.rPaydetailEntry.payAmt;
			var payCrDrObj = settlement.rPaydetailEntry.crDrFlag;
			var rAmt = formatService.parseNumber(payAmtObj);
			var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("C", "paydetail", baseCcy, payCcyVal);
			var adjustAmtInPayCcy = getFinalAmt(adjustAmt, adjustCcy, payCcyVal, adjustCcyFxRate, payCcyFxRate);
			if (isHaveDiscrepancy(settlement)) {
				var disPayAmtObj = settlement.disEntry.payAmt;
				var disPayCrDrObj = settlement.disEntry.crDrFlag;
				var disAmt = formatService.parseNumber(disPayAmtObj);
				// alert("deductPriorityAmt 000: disAmt="+disAmt+",adjustAmtInPayCcy="+adjustAmtInPayCcy);
				if (disPayCrDrObj == "C") {// credit discrepancy
					rAmt = arithService.calc(rAmt, disAmt, "-");
					if (adjustAmtInPayCcy <= disAmt) {
						// reset credit discrepancy
						disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "-");
						rAmt = arithService.calc(rAmt, disAmt, "+");
						settlement.disEntry.payAmt = disAmt;
						settlement.rPaydetailEntry.payAmt = rAmt;
						// reset currect entry
						setledAmt = arithService.calc(setledAmt, adjustAmtInItemCcy, "+");
						// reset adjustAmt
						adjustAmt = 0;
					} else {
						// reset index payAmt
						setledAmt = arithService.calc(setledAmt, getFinalAmt(disAmt, payCcyVal, itemCcy, payCcyFxRate, itemFxRate2), "+");
						// reset adjustAmt
						adjustAmtInPayCcy = arithService.calc(adjustAmtInPayCcy, disAmt, "-");
						adjustAmt = getFinalAmt(adjustAmtInPayCcy, payCcyVal, adjustCcy, payCcyFxRate, adjustCcyFxRate);
						// reset discrepancy paydetail and itemSubtype(R) paydetail
						disAmt = 0;
						settlement.disEntry.payAmt = disAmt;
						rAmt = collectRPaydetailAmt(settlement, startOrder, payMethodVal, settlement.rPaydetailEntry.crDrFlag, obj.amtType, false);
						rAmt = arithService.calc(rAmt, disAmt, "+");
						settlement.rPaydetailEntry.payAmt = rAmt;
						// alert("deductPriorityAmt credit: adjustAmt="+adjustAmt+",setledAmt="+setledAmt+",rAmt="+rAmt);
						// get surplus amount(adjustAmtInPayCcy) from the lower
						// priority items
						var maxIndex = settlement.setlDetails.length;
						for (var i = (maxIndex - 1); i >= 0; i--) {
							if (arithService.lte(adjustAmt, 0))
								break;
							var itemTypeObj = settlement.setlDetails[i].itemType;
							if (!itemTypeObj)
								continue;
							var itemOrderVal = settlement.setlDetails[i].itemOrder;
							// alert("deductPriorityAmt credit: itemOrderVal="+itemOrderVal+",startOrder="+startOrder);
							if ((settlement.priorityList[itemOrderVal] != null) && (itemOrderVal * 1 > startOrder * 1)) {
								// alert("deductPriorityAmt credit: priority itemOrderVal="+itemOrderVal+",startOrder="+startOrder);
								var nextSetlDetail = settlement.priorityList[itemOrderVal];
								var nextPayItemSeqObj = nextSetlDetail.paydetailSeq;
								var nextSetledAmtObj = nextSetlDetail.itemAmtSettled;
								var nextSetledAmt = formatService.parseNumber(nextSetledAmtObj);
								if (nextSetledAmt == 0)
									// because setledAmt is 0(not hold) when it can"t be paid out
									continue;
								if (nextSetlDetail.paydetailSeq_Readonly == false) {// paid out
									var nextItemAmt = formatService.parseNumber(nextSetlDetail.itemAmt);
									var nextItemCcy = nextSetlDetail.itemCcy;
									var nextItemType = nextSetlDetail.itemType;
									var nextItemFxRate2 = nextSetlDetail.fxRate2 - 0;
									if (nextItemFxRate2 == 0)
										nextItemFxRate2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, nextItemCcy);
									var adjustAmtInNextCcy = getFinalAmt(adjustAmt, adjustCcy, nextItemCcy, adjustCcyFxRate, nextItemFxRate2);
									if (adjustAmtInNextCcy < nextSetledAmt) {
										if (nextItemType == "P" || nextItemType == "I") {
											setledAmt = arithService.calc(setledAmt, getFinalAmt(adjustAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2), "+");
											// reset next item
											nextSetledAmt = arithService.calc(nextSetledAmt, adjustAmtInNextCcy, "-");
											setlDetailService.setSetlDetailItemAmtSetled(nextSetlDetail, nextSetledAmt);
											resetSetlDetailPayAmt(settlement, nextSetlDetail, "Y");
											payDetailService.changePaydetailBySetldetail(settlement, nextSetlDetail);
											// reset adjustAmt
											adjustAmt = 0;
											break;
										} else {// nextItemType=="F"
											setledAmt = arithService.calc(setledAmt, getFinalAmt(adjustAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2), "+");
											// fee not paid out fully, change to a debit discrepancy
											disAmt = getFinalAmt(adjustAmt, adjustCcy, payCcyVal, adjustCcyFxRate, payCcyFxRate);
											settlement.disEntry.payAmt = disAmt;
											settlement.disEntry.crDrFlag = "D";
											payDetailService.dynamicChangeThePayCodeList(settlement.disEntry, settlement);
											resetDispPaydetailAcctByInstruction(settlement, "D", settlement.disEntry);
											// reset adjustAmt
											adjustAmt = 0;
											break;
										}
									} else {
										// reset adjustAmt
										adjustAmtInNextCcy = arithService.calc(adjustAmtInNextCcy, nextSetledAmt, "-");
										adjustAmt = getFinalAmt(adjustAmtInNextCcy, nextItemCcy, adjustCcy, nextItemFxRate2, adjustCcyFxRate);
										// reset current entry
										setledAmt = arithService.calc(setledAmt, getFinalAmt(nextSetledAmt, nextItemCcy, itemCcy, nextItemFxRate2, itemFxRate2), "+");
										// alert("deductPriorityAmt credit: adjustAmt="+adjustAmt+",setledAmt="+setledAmt);
										// set the itemAmtSettled of the next item as zero
										nextSetledAmt = 0;
										setlDetailService.setSetlDetailItemAmtSetled(nextSetlDetail, nextSetledAmt);
										resetSetlDetailPayAmt(settlement, nextSetlDetail);
										payDetailService.changePaydetailBySetldetail(settlement, nextSetlDetail);
									}
								}
							}
						}
					}
				} else {// debit discrepancy get surplus amount(adjustAmtInPayCcy) from the lower priority items
					for (var i = (settlement.setlDetails.length - 1); i >= 0; i--) {
						if (arithService.lte(adjustAmt, 0))
							break;
						var itemTypeObj = settlement.setlDetails[i].itemType;
						if (!itemTypeObj)
							continue;
						var itemOrderVal = settlement.setlDetails[i].itemOrder;
						if ((settlement.priorityList[itemOrderVal] != null) && (itemOrderVal * 1 > startOrder * 1)) {
							var tmpAmt = adjustAmt;
							if (arithService.gt(disAmt, 0))
								tmpAmt = arithService.calc(adjustAmt, getFinalAmt(disAmt, payCcyVal, adjustCcy, payCcyFxRate, adjustCcyFxRate), "+");
							var nextSettlDetail = settlement.priorityList[itemOrderVal];
							var nextPayItemSeqObj = nextSettlDetail.paydetailSeq;
							var nextSetledAmtObj = nextSettlDetail.itemAmtSettled;
							var nextSetledAmt = formatService.parseNumber(nextSetledAmtObj);
							if (arithService.eq(nextSetledAmt, 0))
								continue;
							if (nextSettlDetail.Readonly == false) {
								var nextItemAmt = formatService.parseNumber(nextSettlDetail.itemAmt);
								var nextItemCcy = nextSettlDetail.itemCcy;
								var nextItemType = nextSettlDetail.itemType;
								var nextItemFxRate2 = nextSettlDetail.fxRate2 - 0;
								if (arithService.eq(nextItemFxRate2, 0))
									nextItemFxRate2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, nextItemCcy);
								var tmpAmtInNextCcy = getFinalAmt(tmpAmt, adjustCcy, nextItemCcy, adjustCcyFxRate, nextItemFxRate2);
								if (arithService.lte(nextSetledAmt, tmpAmtInNextCcy)) {
									// reset adjustAmt
									var amt = arithService.calc(nextSetledAmt, getFinalAmt(disAmt, payCcyVal, nextItemCcy, payCcyFxRate, nextItemFxRate2), "-");
									adjustAmt = arithService.calc(adjustAmt, getFinalAmt(amt, nextItemCcy, adjustCcy, nextItemFxRate2, adjustCcyFxRate), "-");
									// add the amount to current entry
									setledAmt = arithService.calc(setledAmt, getFinalAmt(amt, nextItemCcy, itemCcy, nextItemFxRate2, itemFxRate2), "+");
									if (arithService.gt(disAmt, 0)) {
										disAmt = 0;
										settlement.disEntry.payAmt = disAmt;
									}
									// set zero to itemAmtSettled of the next item
									nextSetledAmt = 0;
									setlDetailService.setSetlDetailItemAmtSetled(nextSettlDetail, nextSetledAmt);
									resetSetlDetailPayAmt(settlement, nextSettlDetail);
									payDetailService.changePaydetailBySetldetail(settlement, nextSettlDetail);
								} else {
									if (nextItemType == "P" || nextItemType == "I") {
										// reset next item
										nextSetledAmt = arithService.calc(nextSetledAmt, tmpAmtInNextCcy, "-");
										setlDetailService.setSetlDetailItemAmtSetled(nextSettlDetail, nextSetledAmt);
										resetSetlDetailPayAmt(settlement, nextSettlDetail, "Y");
										payDetailService.changePaydetailBySetldetail(settlement, nextSettlDetail);
										// add the amount to current entry
										setledAmt = arithService.calc(setledAmt, getFinalAmt(tmpAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2), "+");
										// reset adjustAmt
										adjustAmt = 0;
										break;
									} else {// nextItemType=="F"
										// create a debit discrepancy
										disAmt = getFinalAmt(tmpAmt, adjustCcy, payCcyVal, adjustCcyFxRate, payCcyFxRate);
										settlement.disEntry.payAmt = disAmt;
										// add the amount to current entry
										setledAmt = arithService.calc(setledAmt, getFinalAmt(adjustAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2), "+");
										// reset adjustAmt
										adjustAmt = 0;
										break;
									}
								}
							}
						}
					}
				}
			} else {// no discrepancy
				// get surplus amount(adjustAmtInPayCcy) from the lower priority items
				for (var i = (settlement.setlDetails.length - 1); i >= 0; i--) {
					if (arithService.lte(adjustAmt, 0))
						break;
					var itemTypeObj = settlement.setlDetails[i].itemType;
					if (!itemTypeObj)
						continue;
					var itemOrderVal = settlement.setlDetails[i].itemOrder;
					if ((settlement.priorityList[itemOrderVal] != null) && (itemOrderVal * 1 > startOrder * 1)) {
						var tmpAmt = adjustAmt;
						var nextSettDetail = settlement.priorityList[itemOrderVal];
						var nextPayItemSeqObj = nextSettDetail.paydetailSeq;
						var nextSetledAmtObj = nextSettDetail.itemAmtSettled;
						var nextSetledAmt = formatService.parseNumber(nextSetledAmtObj);
						if (arithService.eq(nextSetledAmt, 0))
							continue;
						if (nextSettDetail.paydetailSeq_Readonly == false) {
							var nextItemAmt = formatService.parseNumber(nextSettDetail.itemAmt);
							var nextItemCcy = nextSettDetail.itemCcy;
							var nextItemType = nextSettDetail.itemType;
							var nextItemFxRate2 = nextSettDetail.fxRate2 - 0;
							if (arithService.eq(nextItemFxRate2, 0))
								nextItemFxRate2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, nextItemCcy);
							var tmpAmtInNextCcy = getFinalAmt(tmpAmt, adjustCcy, nextItemCcy, adjustCcyFxRate, nextItemFxRate2);
							if (arithService.lte(nextSetledAmt, tmpAmtInNextCcy)) {
								// reset adjustAmt
								tmpAmtInNextCcy = arithService.calc(tmpAmtInNextCcy, nextSetledAmt, "-");
								adjustAmt = getFinalAmt(tmpAmtInNextCcy, nextItemCcy, adjustCcy, nextItemFxRate2, adjustCcyFxRate);
								// add the amount to current entry
								setledAmt = arithService.calc(setledAmt, getFinalAmt(nextSetledAmt, nextItemCcy, itemCcy, nextItemFxRate2, itemFxRate2), "+");
								// set zero to itemAmtSettled of the next item
								nextSetledAmt = 0;
								setlDetailService.setSetlDetailItemAmtSetled(nextSettDetail, nextSetledAmt);
								resetSetlDetailPayAmt(settlement, nextSettDetail);
								payDetailService.changePaydetailBySetldetail(settlement, nextSettDetail);
							} else {
								if (nextItemType == "P" || nextItemType == "I") {
									// reset next item
									nextSetledAmt = arithService.calc(nextSetledAmt, tmpAmtInNextCcy, "-");
									setlDetailService.setSetlDetailItemAmtSetled(nextSettDetail, nextSetledAmt);
									resetSetlDetailPayAmt(settlement, nextSettDetail, "Y");
									payDetailService.changePaydetailBySetldetail(settlement, nextSettDetail);
									// add the amount to current entry
									setledAmt = arithService.calc(setledAmt, getFinalAmt(tmpAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2), "+");
									// reset adjustAmt
									adjustAmt = 0;
									break;
								} else {// nextItemType=="F"
									// create a new debit discrepancy
									createDiscrepancyPaydetail(settlement, payCcyVal, "D", getFinalAmt(tmpAmt, adjustCcy, payCcyVal, adjustCcyFxRate, payCcyFxRate));
									// add the amount to current entry
									setledAmt = arithService.calc(setledAmt, getFinalAmt(tmpAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2), "+");
									// reset adjustAmt
									adjustAmt = 0;
									break;
								}
							}
						}
					}
				}
			}
			// alert("deductPriorityAmt 333: adjustAmt="+adjustAmt+",setledAmt="+setledAmt);
			// update current entry"s payAmt
			if (obj.amtType == "item") {
				if (arithService.gt(setledAmt, 0)) {
					var limitMaxFlag = "Y";
					if ((arithService.gt(adjustAmt, 0)) && (itemType == "F")) {
						limitMaxFlag = "N";
						var debitDisAmt = arithService.calc(itemAmt, setledAmt, "-");
						debitDisAmt = getFinalAmt(debitDisAmt, itemCcy, payCcyVal, itemFxRate2, payCcyFxRate);
						if (disEntry != null) {
							settlement.disEntry.payAmt = debitDisAmt;
							settlement.disEntry.crDrFlag = "D";
							payDetailService.dynamicChangeThePayCodeList(settlement.disEntry, settlement);
							resetDispPaydetailAcctByInstruction(settlement, "D", settlement.disEntry);
							// paid whole itemAmt
							setledAmt = itemAmt;
						} else {
							// create a new debit discrepancy
							createDiscrepancyPaydetail(settlement, payCcyVal, "D", debitDisAmt);
						}
						// alert("deductPriorityAmt 444: adjustAmt="+adjustAmt+",setledAmt="+setledAmt+",debitDisAmt="+debitDisAmt);
						rAmt = arithService.calc(rAmt, debitDisAmt, "-");
						settlement.rPaydetailEntry.payAmt = rAmt;
					}
					setlDetailService.setSetlDetailItemAmtSetled(setlDetail, setledAmt);
					resetSetlDetailPayAmt(settlement, setlDetail, limitMaxFlag);
					// alert("deductPriorityAmt end: adjustAmt="+adjustAmt+",setledAmt="+setledAmt+",debitDisAmt="+debitDisAmt);
					payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
				} else {// means nothing changed
					setlDetailService.setSetlDetailItemAmtSetled(setlDetail, 0);
					resetSetlDetailPayAmt(settlement, setlDetail);
					payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
				}
			}
		}

		/***********************************************************************
		 * add the amount to the lower priority item than this start order obj:
		 * the Object, fields: ccy,order,amtType,amt
		 **********************************************************************/
		function addPriorityAmt(settlement, obj) {
			var adjustAmt = obj.amt;
			var adjustCcy = obj.ccy;
			var startOrder = obj.order;
			var adjustCcyFxRate = obj.fxRate;
			var baseCcy = settlement.site.baseCcy;
			var isAllFeePaidOut = true;
			if (isHaveDiscrepancy(settlement)) {
				// check if C or D
				var disPayAmtObj = settlement.disEntry.payAmt;
				var payCcyVal = settlement.disEntry.payCcy;
				var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("C", "paydetail", baseCcy, payCcyVal);
				var disPayCrDrObj = settlement.disEntry.crDrFlag;
				var disAmt = formatService.parseNumber(disPayAmtObj);
				var adjustAmtInPayCcy = getFinalAmt(adjustAmt, adjustCcy, payCcyVal, adjustCcyFxRate, payCcyFxRate);
				var payMethodVal = settlement.rPaydetailEntry.payItemSeq;
				var payAmtObj = settlement.rPaydetailEntry.payAmt;
				var rAmt = formatService.parseNumber(payAmtObj);
				if (disPayCrDrObj == "C") {
					rAmt = arithService.calc(rAmt, disAmt, "-");
					disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "+");
					rAmt = arithService.calc(rAmt, disAmt, "+");
					settlement.disEntry.payAmt = disAmt;
					settlement.rPaydetailEntry.payAmt = rAmt;
					adjustAmt = 0;
				} else {
					disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "-");
					if (arithService.gte(disAmt, 0)) {
						rAmt = arithService.calc(rAmt, adjustAmtInPayCcy, "+");
						settlement.rPaydetailEntry.payAmt = rAmt;
						settlement.disEntry.payAmt = disAmt;
						adjustAmt = 0;
					} else {
						adjustAmt = getFinalAmt((-disAmt), payCcyVal, adjustCcy, payCcyFxRate, adjustCcyFxRate);
						disAmt = 0;
						settlement.disEntry.payAmt = disAmt;
						// updated on 2007.4.14
						// the collectRPaydetailAmt"s input 3rd parameter is D always, don"t use the payCrDrObj.value, because the
						// rPaydetailEntryIndex paydetail item amount can be less than the deleted settlement
						// detail item amount, in this case the rPaydetailEntryIndex crDr can be changed to credit
						// from original debit. in fact, the rPaydetailEntryIndex crdr always is debit.
						var isDeductThisAmt = false;
						if (settlement.rPaydetailEntry.crDrFlag == "C") {
							settlement.rPaydetailEntry.crDrFlag = "D";
							// rPaydetailEntryIndex amount < settlement detail
							// item amount,so rPaydetailEntryIndex changed from debit to credit.
							// Up to now, the event source settlement detail item is staying on screen,
							// collectRPaydetailAmt return result which shouldn"t include the event source
							// settlement detail item amount if event soure paymethod is same as rPaydetailEntryIndex item"s paymethod.
							isDeductThisAmt = true;
						}
						rAmt = collectRPaydetailAmt(settlement, startOrder, payMethodVal, settlement.rPaydetailEntry.crDrFlag, obj.amtType, isDeductThisAmt);
						settlement.rPaydetailEntry.payAmt = rAmt;
					}
				}
			}
			// alert("addPriorityAmt: 111 adjustAmt="+adjustAmt);
			if (arithService.gt(adjustAmt, 0)) {
				for ( var i in settlement.priorityList) {
					if (arithService.lte(adjustAmt, 0)) {
						break;
					}
					// alert("addPriorityAmt:222 itemOrder="+i+",startOrder="+startOrder);
					if ((settlement.priorityList[i] != null) && (i * 1 > startOrder * 1)) {
						// alert("addPriorityAmt:222 priority itemOrder="+i+",startOrder="+startOrder);
						var settlementDetailObj = settlement.priorityList[i];
						var payItemSeqObj = settlementDetailObj.paydetailSeq;
						var setledAmt = formatService.parseNumber(settlementDetailObj.itemAmtSettled);
						var itemAmt = formatService.parseNumber(settlementDetailObj.itemAmt);
						var itemCcy = settlementDetailObj.itemCcy;
						var itemType = settlementDetailObj.itemType;
						var itemFxRate2 = settlementDetailObj.fxRate2 - 0;
						if (arithService.eq(itemFxRate2, 0))
							itemFxRate2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, itemCcy);
						if (settlementDetailObj.paydetailSeq_Readonly == false) {
							// current entry is paid
							if (arithService.lt(setledAmt, itemAmt)) {// partially paid
								var disAmt = arithService.calc(itemAmt, setledAmt, "-");
								var disAmtInAdjustCcy = getFinalAmt(disAmt, itemCcy, adjustCcy, itemFxRate2, adjustCcyFxRate);
								// alert("addPriorityAmt:222 adjustAmt="+adjustAmt+",setledAmt="+setledAmt+",itemAmt="+itemAmt+",disAmtInAdjustCcy="+disAmtInAdjustCcy);
								if (arithService.gte(adjustAmt, disAmtInAdjustCcy)) {
									setlDetailService.setSetlDetailItemAmtSetled(settlementDetailObj, itemAmt);
									var result = resetSetlDetailPayAmt(settlement, settlementDetailObj, "Y");
									payDetailService.changePaydetailBySetldetail(settlement, settlementDetailObj);
									// if payAmt > maxCanRemitAmt, then itemAmtSetled must be adjusted so reset the adjustAmt in fact
									if (result) {
										var newSetledAmt = formatService.parseNumber(settlementDetailObj.itemAmtSettled);
										disAmt = arithService.calc(newSetledAmt, setledAmt, "-");
										disAmtInAdjustCcy = getFinalAmt(disAmt, itemCcy, adjustCcy, itemFxRate2, adjustCcyFxRate);
									}
									adjustAmt = arithService.calc(adjustAmt, disAmtInAdjustCcy, "-");
								} else {
									var adjustAmtInItemCcy = getFinalAmt(adjustAmt, adjustCcy, itemCcy, adjustCcyFxRate, itemFxRate2);
									setlDetailService.setSetlDetailItemAmtSetled(settlementDetailObj, arithService.calc(setledAmt, adjustAmtInItemCcy, "+"));
									var result = resetSetlDetailPayAmt(settlement, settlementDetailObj, "Y");
									payDetailService.changePaydetailBySetldetail(settlement, settlementDetailObj);
									// if payAmt > maxCanRemitAmt, then itemAmtSetled must be adjusted so reset the adjustAmt in fact
									if (result) {
										var newSetledAmt = formatService.parseNumber(settlementDetailObj.itemAmtSettled);
										disAmt = arithService.calc(newSetledAmt, setledAmt, "-");
										disAmtInAdjustCcy = getFinalAmt(disAmt, itemCcy, adjustCcy, itemFxRate2, adjustCcyFxRate);
										adjustAmt = arithService.calc(adjustAmt, disAmtInAdjustCcy, "-");
									} else {
										adjustAmt = 0;
									}
									if (arithService.eq(adjustAmt, 0))
										break;
								}
							}
						}
					}
				}
				// handle discrepancy
				if (arithService.gt(adjustAmt, 0)) {
					var payCcyVal = settlement.rPaydetailEntry.payCcy;
					var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("C", "paydetail", baseCcy, payCcyVal);
					var payAmtObj = settlement.rPaydetailEntry.payAmt;
					var payCrDrObj = settlement.rPaydetailEntry.crDrFlag;
					var rAmt = formatService.parseNumber(payAmtObj);
					var adjustAmtInPayCcy = getFinalAmt(adjustAmt, adjustCcy, payCcyVal, adjustCcyFxRate, payCcyFxRate);
					// alert("addPriorityAmt:333 rAmt="+rAmt+",disAmt="+disAmt+",adjustAmt="+adjustAmt+",adjustAmtInPayCcy="+adjustAmtInPayCcy+",isAllFeePaidOut="+isAllFeePaidOut);
					if (isAllFeePaidOut) {// credit discrepancy
						if (disEntry != null) {
							var disPayAmtObj = settlement.disEntry.payAmt;
							var disPayCrDrObj = settlement.disEntry.crDrFlag;
							var disAmt = formatService.parseNumber(disPayAmtObj);
							if (disPayCrDrObj == "C") {
								rAmt = arithService.calc(rAmt, disAmt, "-");
								disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "+");
								rAmt = arithService.calc(rAmt, disAmt, "+");
								settlement.disEntry.payAmt = disAmt;
								settlement.rPaydetailEntry.payAmt = rAmt;
							} else {
								disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "-");
								if (arithService.gte(disAmt, 0)) {
									settlement.disEntry.payAmt = disAmt;
								} else {
									disAmt = -disAmt;
									rAmt = arithService.calc(rAmt, disAmt, "+");
									settlement.disEntry.crDrFlag = "C";
									settlement.disEntry.payAmt = disAmt;
									resetDispPaydetailAcctByInstruction(settlement, "C", settlement.disEntry);
									settlement.rPaydetailEntry.payAmt = rAmt;
									// alert("addPriorityAmt:444 rAmt="+rAmt+",disAmt="+disAmt);
								}
							}
						} else {
							// create a new credit discrepancy
							rAmt = arithService.calc(rAmt, adjustAmtInPayCcy, "+");
							createDiscrepancyPaydetail(settlement, payCcyVal, "C", adjustAmtInPayCcy);
							var rAmtFormat = rAmt;
							settlement.rPaydetailEntry.payAmt = rAmtFormat;
						}
					} else {// debit discrepancy
						if (disEntry != null) {
							var disPayAmtObj = settlement.disEntry.payAmt;
							var disPayCrDrObj = settlement.disEntry.crDrFlag;
							var disAmt = formatService.parseNumber(disPayAmtObj);
							if (disPayCrDrObj == "C") {
								rAmt = arithService.calc(rAmt, disAmt, "-");
								disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "-");
								if (arithService.gte(disAmt, 0)) {
									rAmt = arithService.calc(rAmt, disAmt, "+");
								} else {
									disAmt = -disAmt;
									settlement.disEntry.crDrFlag = "D";
									payDetailService.dynamicChangeThePayCodeList(settlement.disEntry, settlement);
									resetDispPaydetailAcctByInstruction(settlement, "D", settlement.disEntry);
								}
								settlement.disEntry.payAmt = disAmt;
								settlement.rPaydetailEntry.payAmt = rAmt;
							} else {
								disAmt = arithService.calc(disAmt, adjustAmtInPayCcy, "+");
								settlement.disEntry.payAmt = disAmt;
							}
						} else {
							// create a new debit discrepancy
							createDiscrepancyPaydetail(settlement, payCcyVal, "D", adjustAmtInPayCcy);
						}
					}
				}
			}
		}

		function doChangefxRateType(settlement, setlDetail, oldPayAmtVal) {
			var order = setlDetail.itemOrdere;
			if (isRemittancePayment(settlement)) {
				var bccy = settlement.site.baseCcy;
				var payccy = setlDetail.payCcy;
				var amt = setlDetailService.calculatePayAmt(settlement.site, setlDetail);
				if (settlement.hasPriority && setlDetail.crDrValue == "D" && settlement.priorityList[order] != null && paydetailSeq_Readonly == false) {
					var payCcyVal = settlement.payment.payCcy;
					var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
					var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
					var fxRate1Val = formatService.parseNumber(setlDetail.fxRate) - 0;
					if (fxRate1Val == 0) {
						fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
					}
					var variableAmt = formatService.parseNumber(amt);
					var crossRateConfig = (itemccy == payCcyVal) ? {
						crossRateFlag : fxCrossRateService.FxCrossRate_Util.getFxCrossRateFlagVal(setlDetail),
						crossRateFromItemCcyToPayCcy : fxCrossRateService.FxCrossRate_Util.getFxCrossRateVal(setlDetail),
						amt : variableAmt,
						amtType : "payAmt"
					} : {};
					var variableAmtInRemitCcy = getFinalAmt(variableAmt, payccy, payCcyVal, fxRate1Val, payCcyFxRate, crossRateConfig);
					// alert("maxRemitAmt="+payAmtTotalVal+",variableAmtInRemitCcy"+variableAmtInRemitCcy);
					if (variableAmtInRemitCcy > payAmtTotalVal) {
						crossRateConfig = (itemccy == payCcyVal) ? {
							crossRateFlag : fxCrossRateService.FxCrossRate_Util.getFxCrossRateFlagVal(setlDetail),
							crossRateFromItemCcyToPayCcy : fxCrossRateService.FxCrossRate_Util.getFxCrossRateVal(setlDetail),
							amt : payAmtTotalVal,
							amtType : "itemAmt"
						} : {};
						variableAmt = getFinalAmt(payAmtTotalVal, payCcyVal, payccy, payCcyFxRate, fxRate1Val, crossRateConfig);
						setlDetail.payAmt = variableAmt;
						var itemAmtValTmp = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
						setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtValTmp);
						payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
					}
					// collection balance from other source
					var dispAmt = arithService.calc(oldPayAmtVal, variableAmt, "-");
					var paramObj = new Object();
					paramObj.ccy = payccy;
					paramObj.fxRate = fxRate1Val;
					paramObj.order = order;
					paramObj.amtType = "pay";
					paramObj.amt = dispAmt;
					adjustPayPriorityAmt(settlement, paramObj);
					formatRemitPayDetailItems(settlement);
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}
		function splitToDeleteSetlDetail(settlement, setlDetail) {
			// 2007.4.12 remittance payment
			if (isRemittancePayment(settlement)) {
				var crDrVal = setlDetail.crDrFlag;
				if (settlement.hasPriority && (crDrVal == "D") && (settlement.settlementInfo.principalAlloc == setlDetail.allocCode)) {
					var itemOrderVal = setlDetail.itemOrder;
					if (settlement.priorityList[itemOrderVal] != null) {
						var usableAmt = setlDetail.itemAmtSettled;
						var usableCcy = setlDetail.itemCcy;
						var payIdObj = setlDetail.paydetailSeq;
						if (setlDetail.paydetailSeq_Readonly == true) {
							usableAmt = 0;
						}
						var fxr2 = setlDetail.fxRate2;
						if (fxr2 == 0) {
							var baseCcy = settlement.site.baseCcy;
							fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
						}
						var paramObj = new Object();
						paramObj.ccy = usableCcy;
						paramObj.fxRate = fxr2;
						paramObj.order = itemOrderVal;
						paramObj.amtType = "item";
						paramObj.amt = usableAmt;

						adjustPayPriorityAmt(settlement, paramObj);
						formatRemitPayDetailItems(settlement);
						settlement.priorityList[itemOrderVal] = null;
						setlDetailService.disableSplit(setlDetail, true);
					} else {
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
					}
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		function doAllocCodeChanged(settlement, setlDetail, parentSetlDetail) {
			// added on
			var howToChangePayCcy = adjustPayCcyByAllocCode(settlement, setlDetail, true, false);
			var itemType = setlDetail.itemType;
			var childFlag = setlDetail.childFlag;
			if ((childFlag == "N") || (childFlag == "Y" && itemType == "P")) {
				setlDetailService.updatePaydetailSeqForSetlDetail(settlement, setlDetail, "allocChange");
			} else {
				if (parentSetlDetail)
					setlDetailService.initSettlementDetailsChildItem(settlement, setlDetail, parentSetlDetail);
			}
			// added on 2006.9.8
			if (howToChangePayCcy == "one") {
				setlDetailService.initializeSetlPayIdData(setlDetail);
				if (setlDetail)
					setlDetailService.setlDetailAddAmt(settlement, setlDetail, "B");
			}
			// 20060807 update the payment detail relative amount
			payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
			// 2006.9.25 remittance payment
			if (isRemittancePayment(settlement)) {
				var crDrValue = setlDetail.crDrFlag;
				var alloc = setlDetail.allocCode;
				// 20060816 add to the pay priority list
				if (settlement.hasPriority && crDrValue == "D") {
					var itemOrderVal = setlDetail.itemOrder;
					var usableAmt = formatService.parseNumber(setlDetail.itemAmtSettled);
					var usableCcy = setlDetail.itemCcy;
					var payIdObj = setlDetail.paydetailSeq;
					if (setlDetail.paydetailSeq_Readonly == true) {
						usableAmt = 0;
					}
					if (settlement.settlementInfo.principalAlloc == alloc) {
						if (settlement.priorityList[itemOrderVal] == null && (isControllPriority(settlement, setlDetail))) {
							var fxr2 = formatService.parseNumber(setlDetail.fxRate2) - 0;
							if (fxr2 == 0) {
								var baseCcy = settlement.site.baseCcy;
								fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
							}
							setlDetailService.disableSplit(setlDetail, false);
							settlement.priorityList[itemOrderVal] = setlDetail;
							var paramObj = new Object();
							paramObj.amt = -usableAmt;
							paramObj.ccy = usableCcy;
							paramObj.fxRate = fxr2;
							paramObj.order = itemOrderVal;
							paramObj.amtType = "item";
							adjustPayPriorityAmt(settlement, paramObj);
							formatRemitPayDetailItems(settlement);
						}
					} else {
						if (settlement.priorityList[itemOrderVal] != null) {
							var fxr2 = formatService.parseNumber(setlDetail.fxRate2) - 0;
							if (fxr2 == 0) {
								var baseCcy = settlement.site.baseCcy;
								fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
							}
							var paramObj = new Object();
							paramObj.amt = usableAmt;
							paramObj.ccy = usableCcy;
							paramObj.fxRate = fxr2;
							paramObj.order = itemOrderVal;
							paramObj.amtType = "item";
							adjustPayPriorityAmt(settlement, paramObj);
							formatRemitPayDetailItems(settlement);
							settlement.priorityList[itemOrderVal] = null;
							setlDetailService.disableSplit(setlDetail, true);
							// added on 2006.9.14 Check the payAmt
							var payAmtVal = formatService.parseNumber(setlDetail.payAmt);
							if (payAmtVal == 0) {
								var itemAmtVal = formatService.parseNumber(setlDetail.itemAmt);
								setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtVal);
								resetSetlDetailPayAmt(settlement, setlDetail, "N");
								payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
							}
						}
					}
				}
				resetRPaydetailEntryCrdr(settlement);
				formatRemitPayDetailItems(settlement);
			}
		}
		/***********************************************************************
		 * Adjust the settlement detail payCcy by allocCode itemNo: the index of
		 * settlement details isDeletePayAmt: true or false indicating if delete
		 * the old payAmt from payDetail entry isInitSetlPayIdData: true or
		 * false indicating if initialize the SetlPayIdData return true if
		 * changed payCcy, otherwise false.
		 **********************************************************************/
		function adjustPayCcyByAllocCode(settlement, setlDetail, isDeletePayAmt, isInitSetlPayIdData) {
			var includeFeeVal = settlement.payment.incFeeFlag;
			var itemTypeVal = setlDetail.itemType;
			var crDrVal = setlDetail.crDrFlag;
			var allocVal = setlDetail.allocCode;
			var payCcyObj = setlDetail.payCcy;
			var oldPayCcyVal = setlDetail.payCcy;
			var txnccy = settlement.payment.payCcy;

			var result = "";
			if (itemTypeVal == "F" && crDrVal == "D" && includeFeeVal == "Y") {
				if (allocVal == settlement.settlementInfo.principalAlloc)
					result = "one";
				else
					result = "more";
			} else if (itemTypeVal == "F" && crDrVal == "D")
				result = "no";

			if (result == "one") {
				if (isDeletePayAmt && setlDetail)// delete old
					setlDetailService.setlDetailDeleteAmt(settlement, setlDetail, "B");
				if (oldPayCcyVal == txnccy) {
					adjustPayCcySelectOptions(setlDetail, txnccy, "one");
				} else {
					adjustPayCcySelectOptions(setlDetail, txnccy, "one");
					setlDetailService.resetFxRatesAmdPayAmt(settlement, setlDetail);
					setlDetailService.updatePaydetailSeqForSetlDetail(settlement, setlDetail, "payCcyChange");
					if (isInitSetlPayIdData)
						setlDetailService.initializeSetlPayIdData(setlDetail);
				}
			} else if (result == "more") {
				adjustPayCcySelectOptions(setlDetail, oldPayCcyVal, "more");
			}
			return result;
		}

		/***********************************************************************
		 * Set the payCcy form object"s options. type: the operation type: one
		 * or more
		 **********************************************************************/
		function adjustPayCcySelectOptions(setlDetail, ccyVal, type) {
			if (setlDetail.payCcy && setlDetail.payCcyOptions) {
				setlDetail.payCcyOptions.data = [];
			}
			if (type == null || type == "")
				type = "more";
			if (type == "one") {
				var opt = {
					"value" : ccyVal,
					"label" : ccyVal
				};
				if (setlDetail.payCcy && setlDetail.payCcyOptions && setlDetail.payCcyOptions.data)
					setlDetail.payCcyOptions.data.push(opt);
			} else {
//				setlDetail.payCcyOptions = settlement.payCcyOptions;
			}
			setlDetail.payCcy = ccyVal;
		}
		function itemWaiveFlagChanged(settlement, setlDetail) {
			// 20060818 add the pay priority codes
			var isControlPayPriority = false;
			var itemOrderVal = setlDetail.itemOrder;
			// 2006.9.25 remittance payment
			if (isRemittancePayment(settlement)) {
				// if no pay priority
				if (!settlement.hasPriority) {// none
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				} else {
					if (settlement.priorityList[itemOrderVal] != null)
						isControlPayPriority = true;
					if (isControlPayPriority) {
						uncheckedBox(settlement, setlDetail, "waive");
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
						if (!(waive == "Y"))
							setlDetailService.disableSplit(setlDetail, false);
					} else {
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
					}
				}
			}
		}

		/***********************************************************************
		 * process adjusting priority in case of checkbox checked/unchecked. If
		 * it can be checked/unchecked, only calculate the new payAmt. Now it
		 * only support hold/waive checkbox.Don"t call it directly except
		 * hold/waive method. index: the index of the settlement details
		 **********************************************************************/
		function uncheckedBox(settlement, setlDetail, type) {
			var usableCcy = setlDetail.itemCcy;
			var order = setlDetail.itemOrder;
			var usableAmt = formatService.parseNumber(setlDetail.itemAmtSettled);
			if (type == "hold") {
				var holdObj = setlDetail.itemHoldFlag;
				if (!(holdObj == "Y")) {
					adjustPayAmtForPayPriority(settlement, setlDetail);
					usableAmt = formatService.parseNumber(setlDetail.itemAmtSettled);
					usableAmt = -usableAmt;
				}
			} else if (type == "waive") {
				var waive = setlDetail.itemWaiveFlag;
				if (!(waive == "Y")) {
					adjustPayAmtForPayPriority(settlement, setlDetail);
					usableAmt = formatService.parseNumber(setlDetail.itemAmtSettled);
					usableAmt = -usableAmt;
				}
			}
			if (usableAmt != 0) {
				var fxr2 = setlDetail.fxRate2 - 0;
				if (fxr2 == 0) {
					var baseCcy = settlement.site.baseCcy;
					fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
				}
				var paramObj = new Object();
				paramObj.amt = usableAmt;
				paramObj.ccy = usableCcy;
				paramObj.fxRate = fxr2;
				paramObj.order = order;
				paramObj.amtType = "item";
				adjustPayPriorityAmt(settlement, paramObj);
			}
		}

		function itemHoldFlagChanged(settlement, setlDetail) {
			// 2006.9.25 remittance payment
			if (isRemittancePayment(settlement)) {
				// 20060818 add the pay priority codes
				var isControlPayPriority = false;
				var itemOrderVal = setlDetail.itemOrder;
				// if no pay priority
				if (!settlement.hasPriority) {// none
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				} else {
					if (settlement.priorityList[itemOrderVal] != null)
						isControlPayPriority = true;
					if (isControlPayPriority) {
						uncheckedBox(settlement, itemNo, "hold");
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
						if (holdObj == "N")
							setlDetailService.disableSplit(setlDetail, false);
					} else {
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
					}
				}
			}
		}

		function taxWaiveFlagChanged(settlement, setlDetail, payAmtOld) {
			// 20070419 add pay priority
			if (isRemittancePayment(settlement)) {
				var order = setlDetail.itemOrder;
				var crDrValue = setlDetail.crDrFlag;
				if (settlement.hasPriority && crDrValue == "D" && settlement.priorityList[order] != null && setlDetail.payItemSeq_Readonly == false) {
					var bccy = settlement.site.baseCcy;
					var payccy = setlDetail.payCcy;
					var payCcyVal = settlement.payment.payCcy;
					var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
					var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
					var fxRate1Val = formatService.parseNumber(setlDetail.fxRate) - 0;
					if (fxRate1Val == 0) {
						fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
					}
					var variableAmt = formatService.parseNumber(amt);
					var variableAmtInRemitCcy = getFinalAmt(variableAmt, payccy, payCcyVal, fxRate1Val, payCcyFxRate);
					// alert("maxRemitAmt="+payAmtTotalVal+",variableAmtInRemitCcy"+variableAmtInRemitCcy);
					if (variableAmtInRemitCcy > payAmtTotalVal) {
						variableAmt = getFinalAmt(payAmtTotalVal, payCcyVal, payccy, payCcyFxRate, fxRate1Val);
						setlDetail.payAmt = variableAmt;
						var itemAmtValTmp = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
						setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtValTmp);
						payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
					}
					// collection balance from other source
					var dispAmt = arithService.calc(payAmtOld, variableAmt, "-");
					var paramObj = new Object();
					paramObj.ccy = payccy;
					paramObj.fxRate = fxRate1Val;
					paramObj.order = order;
					paramObj.amtType = "pay";
					paramObj.amt = dispAmt;
					adjustPayPriorityAmt(settlement, paramObj);
					formatRemitPayDetailItems(settlement);
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		function fxCrossRateFlagChanged(settlement, setlDetail) {
			if (isRemittancePayment(settlement)) {
				var order = setlDetail.itemOrder;
				var crDrValue = setlDetail.crDrFlag;
				if (settlement.hasPriority && crDrValue == "D" && settlement.priorityList[order] != null && setlDetail.paydetailSeq_Readonly == false) {
					var bccy = settlement.site.baseCcy;
					var payccy = setlDetail.payCcy;
					var payCcyVal = settlement.payment.payCcy;
					var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
					var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
					var fxRate1Val = formatService.parseNumber(setlDetail.fxRate) - 0;
					if (fxRate1Val == 0) {
						fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
					}
					var variableAmt = formatService.parseNumber(amt);
					var crossRateFlag = (itemCcy == payCcyVal) ? {
						crossRateFlag : fxCrossRateService.FxCrossRate_Util.getFxCrossRateFlagVal(setlDetail),
						crossRateFromItemCcyToPayCcy : fxCrossRateService.FxCrossRate_Util.getFxCrossRateVal(setlDetail),
						amt : variableAmt,
						amtType : "payAmt"
					} : {};
					var variableAmtInRemitCcy = getFinalAmt(variableAmt, payccy, payCcyVal, fxRate1Val, payCcyFxRate, crossRateFlag);
					// alert("maxRemitAmt="+payAmtTotalVal+",variableAmtInRemitCcy"+variableAmtInRemitCcy);
					if (variableAmtInRemitCcy > payAmtTotalVal) {
						crossRateFlag = (itemCcy == payCcyVal) ? {
							crossRateFlag : fxCrossRateService.FxCrossRate_Util.getFxCrossRateFlagVal(setlDetail),
							crossRateFromItemCcyToPayCcy : fxCrossRateService.FxCrossRate_Util.getFxCrossRateVal(setlDetail),
							amt : payAmtTotalVal,
							amtType : "itemAmt"
						} : {};
						variableAmt = getFinalAmt(payAmtTotalVal, payCcyVal, payccy, payCcyFxRate, fxRate1Val, crossRateFlag);
						setlDetail.payAmt = variableAmt;
						var itemAmtValTmp = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
						setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtValTmp);
						payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
					}
					// collection balance from other source
					var dispAmt = arithService.calc(oldPayAmtVal, variableAmt, "-");
					var paramObj = new Object();
					paramObj.ccy = payccy;
					paramObj.fxRate = fxRate1Val;
					paramObj.order = order;
					paramObj.amtType = "pay";
					paramObj.amt = dispAmt;
					adjustPayPriorityAmt(settlement, paramObj);
					formatRemitPayDetailItems(settlement);
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		function getCcy(settlement) {
			return settlement.payment.repayCcy;
		}

		function feeBoxForPayCodeFee(settlement, param, setlDetail) {
			// 20060815 add to pay priority list
			if (isControllPriority(settlement, setlDetail)) {
				settlement.priorityList[setlDetail.itemOrder] = setlDetail;
				setlDetailService.disableSplit(setlDetail, false);
			}
			// 2006.9.8
			adjustPayCcyByAllocCode(settlement, setlDetail, false, true);
			// 20060808 add the amount to payment detail
			if (setlDetail)
				setlDetailService.setlDetailAddAmt(settlement, setlDetail, "B");
			// //2006.9.25 remittance payment
			if (isRemittancePayment(settlement)) {
				// 20060817 add the pay priority
				if (settlement.hasPriority && (settlement.settlementInfo.principalAlloc == param.allocCode) && (param.crdr == "D")) {
					var itemOrderVal = setlDetail.itemOrder;
					if (settlement.priorityList[itemOrderVal] != null) {
						var usableAmt = formatService.parseNumber(setlDetail.itemAmtSettled);
						var usableCcy = setlDetail.itemCcy;
						var fxr2 = formatService.parseNumber(setlDetail.fxRate2) - 0;
						var payIdObj = setlDetail.paydetailSeq;
						if (setlDetail.paydetailSeq_Readonly == true) {
							usableAmt = 0;
						}
						if (fxr2 == 0) {
							var baseCcy = settlement.site.baseCcy;
							fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
						}
						var paramObj = new Object();
						paramObj.fxRate = fxr2;
						paramObj.ccy = usableCcy;
						paramObj.amt = -usableAmt;
						paramObj.order = itemOrderVal;
						paramObj.amtType = "item";
						adjustPayPriorityAmt(settlement, paramObj);
						formatRemitPayDetailItems(settlement);
					} else {
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
					}
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		/***********************************************************************
		 * calculate and reset the payAmt of settlement details. Only when
		 * limitMaxFlag is Y, if payAmt is greater than fact max remit amount,
		 * the itemAmtSetled must be adjusted.The method return true only when
		 * itemAmtSetled is adjusted. otherwise false. itemNo: the index of
		 * settlement details limitMaxFlag: Y or N indicating whether limit the
		 * max pay amount
		 **********************************************************************/
		function resetSetlDetailPayAmt(settlement, setlDetail, limitMaxFlag) {
			var isItemAmtSetledAdjusted = false;
			var amt = setlDetailService.calculatePayAmt(settlement.site, setlDetail);
			setlDetail.payAmt = amt;
			// 20060830 check if over the maxRemitAmt
			var isLimitMax = false;
			if (limitMaxFlag && limitMaxFlag == "Y")
				isLimitMax = true;
			var bccy = settlement.site.baseCcy;
			var payccy = setlDetail.payCcy;
			var order = setlDetail.itemOrder;
			var crDrValue = setlDetail.crDrFlag;

			if (settlement.hasPriority && crDrValue == "D" && settlement.priorityList[order] != null && isLimitMax) {
				var payCcyVal = settlement.payment.payCcy;
				var payCcyFxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payCcyVal);
				var payAmtTotalVal = getMaxRemitAmt(settlement, setlDetail);
				var fxRate1Val = formatService.parseNumber(setlDetail.fxRate) - 0;
				if (fxRate1Val == 0) {
					fxRate1Val = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", bccy, payccy);
				}
				var variableAmt = formatService.parseNumber(amt);
				var variableAmtInRemitCcy = getFinalAmt(variableAmt, payccy, payCcyVal, fxRate1Val, payCcyFxRate);
				// alert("resetSetlDetailPayAmt maxRemitAmt="+payAmtTotalVal+",variableAmtInRemitCcy"+variableAmtInRemitCcy);
				if (variableAmtInRemitCcy > payAmtTotalVal) {
					variableAmt = getFinalAmt(payAmtTotalVal, payCcyVal, payccy, payCcyFxRate, fxRate1Val);
					setlDetail.payAmt = variableAmt;
					var itemAmtValTmp = calculateItemAmtSetledByPayAmt(settlement, setlDetail);
					setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtValTmp);
					isItemAmtSetledAdjusted = true;
				}
			}
			return isItemAmtSetledAdjusted;
		}

		/***********************************************************************
		 * Only when pay priority, collect the itemSubtype==R paydetail entry"s
		 * amount. startOrder: the event source settlement detail"s itemOrder(it
		 * must be in priority control) rPayDetailPayMethodVal: the itemSubtype==R
		 * paydetail entry"s payMethod value rPayDetailCrDrVal: the itemSubtype==R
		 * paydetail entry"s crDr value objAmtType: the amount type: "pay" or
		 * "item" isDeductThisAmt: true or false indicating whether deducted
		 * startOrder settlement detail"s amount from itemSubtype==R paydetail
		 * entry"s amount. This parameter can"t be empty. true stands for need
		 * to deduct.
		 **********************************************************************/
		function collectRPaydetailAmt(settlement, startOrder, rPayDetailPayMethodVal, rPayDetailCrDrVal, objAmtType, isDeductThisAmt) {
			var rAmt = 0;
			var cur = settlement.priorityList[startOrder];
			var continueFlag = true;
			angular.forEach(settlement.setlDetails, function(data, index, array) {
				var itemTypeObj = data.itemType;
				if (itemTypeObj == null)
					continueFlag = false;
				if (continueFlag) {
					var payId = data.paydetailSeq;
					// if(payIdObjTmp.disabled == true)
					// payIdVal = null;
					if (payId != null && rPayDetailPayMethodVal == payId) {
						if (!(data == cur && isDeductThisAmt)) {
							var payAmtInSDVal = formatService.parseNumber(data.payAmt);
							var crDrInSDVal = data.crDrFlag;
							if (rPayDetailCrDrVal == crDrInSDVal)
								rAmt = arithService.calc(rAmt, payAmtInSDVal, "+");
							else
								rAmt = arithService.calc(rAmt, payAmtInSDVal, "-");
						}
					}
				}
			});
			return rAmt;
		}

		/***********************************************************************
		 * Check if have effective discrepancy paydetail return true if have,
		 * otherwise false
		 **********************************************************************/
		function isHaveDiscrepancy(settlement) {
			if (settlement.disEntry == null)
				return false;
			if (formatService.parseNumber(settlement.disEntry.payAmt) == 0)
				return false;
			else
				return true;
		}

		/***********************************************************************
		 * reset the discrepancy payment detail entry"s payCode and acctNo.
		 * crDr: the credit or debit: C or D dispPdIndex: the index of payment
		 * details
		 **********************************************************************/
		function resetDispPaydetailAcctByInstruction(settlement, crDr, payDetail) {
			payDetailService.dynamicChangeThePayCodeList(payDetail, settlement);
			if (settlement.disPayCode[crDr] != null) {
				payDetail.acctNo = settlement.disPayCode[crDr].acctNo;
				payDetail.paycode = settlement.disPayCode[crDr].paycode;
			} else {
				payDetail.acctNo = "";
				payDetail.paycode = "";
			}
			$injector.get("payDetailEventService").paycodeChanged(settlement, payDetail, "new", false, "no");
		}
		function getTxnAmount(settlement) {
			return settlement.payment.paymentPrincAmount;
		}
		function feebox(settlement, param, setlDetail) {
			// 20060815 add to pay priority list
			if (isControllPriority(settlement, setlDetail)) {
				settlement.priorityList[setlDetail.itemOrder] = setlDetail;
				setlDetailService.disableSplit(setlDetail, false);
			}
			// 2006.9.8
			adjustPayCcyByAllocCode(settlement, setlDetail, false, true);
			if (setlDetail)
				setlDetailService.setlDetailAddAmt(settlement, setlDetail, "B");
			// 2006.9.25 remittance payment
			var setl = setlDetail;
			if (isRemittancePayment(settlement)) {
				// 20060817 add the pay priority
				if (settlement.hasPriority && (settlement.settlementInfo.principalAlloc == param.allocCode) && (param.crdr == "D")) {
					var itemOrderVal = setl.itemOrder;
					if (settlement.priorityList[itemOrderVal] != null) {
						var usableAmt = formatService.parseNumber(setl.itemAmtSettled);
						var usableCcy = setl.itemCcy;
						var fxr2 = formatService.parseNumber(setl.fxRate2) - 0;
						if (setl.paydetailSeq_Readonly == true) {
							usableAmt = 0;
						}
						if (fxr2 == 0) {
							var baseCcy = settlement.site.baseCcy;
							fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
						}
						var paramObj = new Object();
						paramObj.fxRate = fxr2;
						paramObj.ccy = usableCcy;
						paramObj.amt = -usableAmt;
						paramObj.order = itemOrderVal;
						paramObj.amtType = "item";
						adjustPayPriorityAmt(settlement, paramObj);
						formatRemitPayDetailItems(settlement);
					} else {
						resetRPaydetailEntryCrdr(settlement);
						formatRemitPayDetailItems(settlement);
					}
				} else {
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}

		function paydetailSeqChanged(settlement, setlDetail) {
			var payDetailSeq = setlDetail.paydetailSeq;
			if (isRemittancePayment(settlement)) {
				if (settlement.hasPriority && setlDetail.crDrFlag == "D") {
					var payMethodVal = settlement.rPaydetailEntry.payItemSeq;
					var itemOrderVal = setlDetail.itemOrder;
					var usableAmt = formatService.parseNumber(setlDetail.itemAmtSettled);
					var usableCcy = setlDetail.itemCcy;
					var payIdObj = setlDetail.paydetailSeq;
					if (payIdObj.paydetailSeq_Readonly == true) {
						usableAmt = 0;
					}
					// alert("selectPayMethod payDetailSeq.value == payMethodVal:"+payDetailSeq.value +"=="+ payMethodVal);
					if (payDetailSeq == payMethodVal) {
						// case: has priority, check include interest, not check include fee this settlement detail entry is debit fee
						// alert("selectPayMethod:" + priorityList[itemOrderVal]);
						if (settlement.priorityList[itemOrderVal] == null) {
							if ((isControllPriority(settlement, setlDetail))) {
								var fxr2 = formatService.parseNumber(setlDetail.fxRate2) - 0;
								if (fxr2 == 0) {
									var baseCcy = settlement.site.baseCcy;
									fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
								}
								setlDetailService.disableSplit(setlDetail, false);
								settlement.priorityList[itemOrderVal] = setlDetail;
								var paramObj = new Object();
								paramObj.amt = -usableAmt;
								paramObj.ccy = usableCcy;
								paramObj.fxRate = fxr2;
								paramObj.order = itemOrderVal;
								paramObj.amtType = "item";
								adjustPayPriorityAmt(settlement, paramObj);
								formatRemitPayDetailItems(settlement);
							} else {
								resetRPaydetailEntryCrdr(settlement);
								formatRemitPayDetailItems(settlement);
							}
						}
					} else {
						if (settlement.priorityList[itemOrderVal] != null) {
							var fxr2 = formatService.parseNumber(setlDetail.fxRate2) - 0;
							if (fxr2 == 0) {
								var baseCcy = settlement.site.baseCcy;
								fxr2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, usableCcy);
							}
							var paramObj = new Object();
							paramObj.amt = usableAmt;
							paramObj.ccy = usableCcy;
							paramObj.fxRate = fxr2;
							paramObj.order = itemOrderVal;
							paramObj.amtType = "item";
							adjustPayPriorityAmt(settlement, paramObj);
							formatRemitPayDetailItems(settlement);
							settlement.priorityList[itemOrderVal] = null;
							setlDetailService.disableSplit(setlDetail, true);
							// added on 2006.9.14 Check the payAmt
							var payAmtVal = formatService.parseNumber(setlDetail.payAmt);
							if (payAmtVal == 0) {
								var itemAmtVal = formatService.parseNumber(setlDetail.itemAmt);
								setlDetailService.setSetlDetailItemAmtSetled(setlDetail, itemAmtVal);
								resetSetlDetailPayAmt(settlement, setlDetail, "N");
								payDetailService.changePaydetailBySetldetail(settlement, setlDetail);
							}
						} else {
							resetRPaydetailEntryCrdr(settlement);
							formatRemitPayDetailItems(settlement);
						}
					}
				}
				// if no pay priority
				if (!settlement.hasPriority) {// none
					resetRPaydetailEntryCrdr(settlement);
					formatRemitPayDetailItems(settlement);
				}
			}
		}
		
		function getLayout(settlement, packageSuffix) {
			return txnService.getLayout("settlement", packageSuffix, false, "REPAYMENT", settlement.loan.loanInfo.prodType, settlement.loan.loanInfo.prodSubtype);
		}

		return {
			changeAmountBox : changeAmountBox,
			doAllocCodeChanged : doAllocCodeChanged,
			doChangefxRateType : doChangefxRateType,
			doChangePayCcy : doChangePayCcy,
			dynamicConfigItemCarryFlag : dynamicConfigItemCarryFlag,
			dynamicConfigItemHoldFlag : dynamicConfigItemHoldFlag,
			dynamicConfigItemTransferFlag : dynamicConfigItemTransferFlag,
			dynamicConfigItemWaiveFlag : dynamicConfigItemWaiveFlag,
			feebox : feebox,
			feeBoxForPayCodeFee : feeBoxForPayCodeFee,
			fxCrossRateChanged : fxCrossRateChanged,
			fxCrossRateFlagChanged : fxCrossRateFlagChanged,
			getBackMessage : getBackMessage,
			getCcy : getCcy,
			getCompanyCodeByAlloc : getCompanyCodeByAlloc,
			getDeductIntAndFeeFlag : getDeductIntAndFeeFlag,
			getGeneralConfig : getGeneralConfig,
			getGeneralModel : getGeneralModel,
			getHoldFeeFlag : getHoldFeeFlag,
			getLayout : getLayout,
			getProdCodeAndType : getProdCodeAndType,
			getTxnAmount : getTxnAmount,
			initSettlement : initSettlement,
			initSettlementData : initSettlementData,
			itemHoldFlagChanged : itemHoldFlagChanged,
			itemWaiveFlagChanged : itemWaiveFlagChanged,
			paydetailSeqChanged : paydetailSeqChanged,
			processDynaparmConfig : processDynaparmConfig,
			resetSetlDetailPayAmt : resetSetlDetailPayAmt,
			splitToDeleteSetlDetail : splitToDeleteSetlDetail,
			taxWaiveFlagChanged : taxWaiveFlagChanged
		};
	}
})(angular);
